home *** CD-ROM | disk | FTP | other *** search
/ Amiga CD-ROM Collection / Amiga CD-ROM Collection - Auge 4000 and Cactus and Demo Util.iso / cactus / 01 / meincli / meincli_source < prev    next >
C/C++ Source or Header  |  1988-05-23  |  35KB  |  1,293 lines

  1. /*
  2.  * MyCLI - a replacement for the standard AmigaDos CLI
  3.  * Programmed by Mike Schwartz (C)1985 MS Software, All Rights Reserved!
  4.  * Feel free to give this software away, in any form, for no charge only.
  5.  * Feel free to donate to:
  6.  * MS Software
  7.  * 344 Fay Way
  8.  * Mountain View, CA 94043
  9.  */
  10.  
  11. #include "exec/types.h"
  12. #include "exec/exec.h"
  13. #include "libraries/dos.h"
  14. #include "libraries/dosextens.h"
  15. #include "devices/serial.h"
  16.  
  17. /*
  18.  * External functions
  19.  */
  20. extern   unsigned char        *stpblk();
  21. extern   unsigned char        *AllocMem();
  22. extern   struct   MsgPort     *CreatePort();
  23. extern   struct   FileLock    *CreateDir();
  24. extern   struct   FileLock    *CurrentDir();
  25. extern   struct   FileLock    *Lock();
  26. extern   struct   FileHandle  *Open();
  27.  
  28. /*
  29.  * forward references
  30.  */
  31. int   capture(), cd(), copy(), date(), define_function_key(), delete(),
  32.       dir(), delete(), endcli(), help(), md(), newcli(), offline(),
  33.       rename(), setprompt(), setcomment(), TerminalMode(), time(), type(),
  34.       whatis();
  35.  
  36. /*
  37.  * Tables
  38.  */
  39. struct {
  40.    unsigned char  *cmdname;
  41.    int            (*cmdfunc)();
  42.    } command_table[] = {
  43.    (unsigned char *)"capture", &capture,
  44.    (unsigned char *)"cd", &cd,
  45.    (unsigned char *)"chdir", &cd,
  46.    (unsigned char *)"copy", ©,
  47.    (unsigned char *)"date", &date,
  48.    (unsigned char *)"define", &define_function_key,
  49.    (unsigned char *)"def", &define_function_key,
  50.    (unsigned char *)"delete", &delete,
  51.    (unsigned char *)"del", &delete,
  52.    (unsigned char *)"dir", &dir,
  53.    (unsigned char *)"erase", &delete,
  54.    (unsigned char *)"endcli", &endcli,
  55.    (unsigned char *)"help", &help,
  56.    (unsigned char *)"makedir", &md,
  57.    (unsigned char *)"md", &md,
  58.    (unsigned char *)"newcli", &newcli,
  59.    (unsigned char *)"online", &TerminalMode,
  60.    (unsigned char *)"offline", &offline,
  61.    (unsigned char *)"rename", &rename,
  62.    (unsigned char *)"ren", &rename,
  63.    (unsigned char *)"prompt", &setprompt,
  64.    (unsigned char *)"setcomment", &setcomment,
  65.    (unsigned char *)"terminal", &TerminalMode,
  66.    (unsigned char *)"time", &time,
  67.    (unsigned char *)"type", &type,
  68.    (unsigned char *)"whatis", &whatis,
  69.    (unsigned char *)"\0", &help,
  70.    };
  71.  
  72. unsigned char  *help_messages[] = {
  73.    "capture    = capture file vom Modem",
  74.    "cd         = aktuelle directory",
  75.    "chdir      = aktuelle directory",
  76.    "copy       = kopiere ein File zu einem anderen",
  77.    "date       = zeige aktuelle Zeit un Datum",
  78.    "def        = definiere eine Funtionstaste",
  79.    "define     = definiere eine Funktionstaste",
  80.    "del        = lösche ein File oder Unterdirectory",
  81.    "delete     = lösche ein File oder Unterdirectory",
  82.    "dir        = directory",
  83.    "erase      = lösche ein File oder Unterdirectory",
  84.    "endcli     = beende aktuelles CLI-Fenster",
  85.    "help       = zeige diese Liste",
  86.    "makedir    = erzeuge ein neues Unterdirectory",
  87.    "md         = erzeuge ein neues Unterdirectory",
  88.    "newcli     = erzeuge ein neues Mein-CLI Fenster",
  89.    "online     = enter or re-enter dumb terminal mode",
  90.    "offline    = beende Kommunikation",
  91.    "ren        = ändere Namen eines Files oder Directorys",
  92.    "rename     = ändere Namen eines Files oder Directorys",
  93.    "prompt     = ändere das Prompt",
  94.    "setcomment = erzeuge File-Kommentar",
  95.    "terminal   = enter or re-enter dumb terminal mode",
  96.    "time       = zeige aktuelle Zeit",
  97.    "type       = zeige ASCI-File",
  98.    0};
  99.  
  100. unsigned char  *function_key_definitions[20] = {
  101.    0,0,0,0,0,0,0,0,0,0,
  102.    0,0,0,0,0,0,0,0,0,0
  103.    };
  104.  
  105. struct   {
  106.    int   code;
  107.    unsigned char  *message;
  108.    } errorcodes[] = {
  109.  
  110.       103,    "nicht genug Speicher",
  111.       104,    "task table voll",
  112.       120,    "Argument falsch oder zu lang",
  113.       121,    "kein ausführbares File",
  114.       122,    "invalid resident library during load",
  115.       203,    "Objekt existiert schon",
  116.       204,    "Directory nicht gefunden",
  117.       205,    "Objekt nicht gefunden",
  118.       206,    "falsches Fenster",
  119.       210,    "Falscher Name",
  120.       212,    "Objekt nicht vom benötigten Typ",
  121.       213,    "Disk nicht validated",
  122.       214,    "Disk schreibgeschützt",
  123.       215,    "rename across devices attempted",
  124.       216,    "Directory nicht leer",
  125.       218,    "Gerät nicht vorhanden",
  126.       220,    "Kommentar zu gross",
  127.       221,    "Disk voll",
  128.       222,    "File ist vor Löschenzugriff geschützt",
  129.       223,    "File ist vor Schreibzugriff geschützt",
  130.       224,    "File ist vor Lesezugriff geschützt",
  131.       225,    "keine DOS-Disk",
  132.       226,    "keine Disk im Laufwerk",
  133.       209,    "benötigter Pakettyp unbekannt",
  134.       211,    "falsche Objektsperre",
  135.       219,    "Such-Fehler",
  136.       232,    "keine weiteren Einträge im Directory",
  137.       0, 0};
  138.  
  139. /*
  140.  * Globals
  141.  */
  142. struct   FileLock       *worklock;
  143. struct   InfoData       disk_info;
  144. struct   FileInfoBlock  fib;
  145. struct   FileHandle     *workfp;
  146.  
  147. unsigned char     work[512];
  148. unsigned char     buf[512];
  149. unsigned char     work2[512];
  150. unsigned char     temp[80];
  151.  
  152. /*
  153.  * MyCli globals
  154.  */
  155. struct   FileHandle     *mycli_infp;
  156. struct   FileHandle     *mycli_outfp;
  157.  
  158. unsigned char     *prompt_string = 0;
  159. unsigned char     current_directory[80];
  160. int      mycli_id = 1;
  161.  
  162. /*
  163.  * Terminal emulator stuff
  164.  */
  165. struct   Message        *mymessage;
  166. struct   IOExtSer       *ModemReadRequest;
  167. struct   IOExtSer       *ModemWriteRequest;
  168.  
  169. unsigned char  *WelcomeMessage = "Eintritt Terminal Mode\n ^C für Kommando Mode\n";
  170. unsigned char  *GoodbyeMessage = "Verbindung beendet\n";
  171. unsigned char  *OfflineMessage = "--- Offline ---\n";
  172. unsigned char  *OnlineMessage = "--- Online ---\n";
  173.  
  174. unsigned char     rs_in[2], rs_out[2];
  175. int      bdoneflag = 0;
  176. int      TermEcho = 0;
  177. int      modem_online = 0;
  178. int      capturing_file = 0;
  179. struct   FileHandle  *capture_fp;
  180.  
  181. main(argc, argv)
  182. int   argc;
  183. unsigned char  *argv[];
  184. {
  185.    if (argc == 2)
  186.       mycli_id = atoi(argv[1]);
  187.    sprintf(work, "Raw:0/%d/639/%d/MeinCli[%d]", (mycli_id-1)*8, 199-(mycli_id-1)*16, mycli_id);
  188.    mycli_infp = Open(work, MODE_NEWFILE);
  189.    if (mycli_infp == 0) {
  190.       printf("Kann kein Fenster öffnen\n");
  191.       exit(1);
  192.       }
  193.    mycli_outfp = mycli_infp;
  194.    sprintf(work, "%c[80uMeinCli\nAutor: Mike Schwartz\n(C)1985 MS Software, all rights reserved!\n Ausgaben Übersetzt von A.U.G.E. 4000", 0x1b);
  195.  
  196. WriteWork();
  197.  
  198.    current_directory[0] = '\0';
  199.    cd("df0:");
  200.    setprompt("$_$r  $d  $n  $p  $r  $t  $n$_>");
  201.    batchfile("df0:autoexec.bat");
  202.  
  203.    while (1) {
  204.       showprompt();
  205.       getcommand(buf);
  206.       CommandInterpreter(buf);
  207.       }
  208.    }
  209.  
  210. WriteWork() {
  211.    Write(mycli_outfp, work, strlen(work));
  212.    }
  213.  
  214. /*
  215.  * Declaring fh as a local in this routine, batch files may be nested
  216.  * as deep as the stack and memory will allow.
  217.  */
  218. batchfile(batchname)
  219. unsigned char  *batchname;
  220. {
  221.    int      i;
  222.    struct   FileHandle  *fh;
  223.  
  224.    fh = Open(batchname, MODE_OLDFILE);
  225.    if (fh != 0) {
  226.       while (1) {
  227.          for (i = 0; ; i++) {
  228.             if (Read(fh, &buf[i], 1) == 0) {
  229.                buf[i] = '\0';
  230.                showprompt();
  231.                sprintf(work, "%s\n", buf);
  232.                WriteWork();
  233.                CommandInterpreter(stpblk(buf));
  234.                Close(fh);
  235.                return !0;
  236.                }
  237.             if (buf[i] == 0x0a)
  238.                break;
  239.             }
  240.          buf[i] = '\0';
  241.          showprompt();
  242.          sprintf(work, "%s\n", buf);
  243.          WriteWork();
  244.          CommandInterpreter(stpblk(buf));
  245.          }
  246.       }
  247.    else
  248.       return 0;
  249.    }
  250.  
  251. CommandInterpreter(command)
  252. unsigned char  *command;
  253. {
  254.    int   i;
  255.  
  256.    command = stpblk(command);
  257.    /*
  258.     * Scan through the command table for the string and invoke the function
  259.     *    to do the actual work of the command.  Each of these commands is
  260.     *    defined below, and the functions each take a pointer to the
  261.     *    string containing the arguments passed the command line.
  262.     */
  263.    for (i=0; command_table[i].cmdname[0] != '\0'; i++)
  264.       if (
  265.          strncmp(command,
  266.               command_table[i].cmdname,
  267.               strlen(command_table[i].cmdname))
  268.                == 0) {
  269.          (*command_table[i].cmdfunc)
  270.             (stpblk(&command[strlen(command_table[i].cmdname)]));
  271.          goto FinishedCommand;
  272.          }
  273.    /*
  274.     * Not found, so look for it on the disk.
  275.     */
  276.    executive(stpblk(&command[0]));
  277. FinishedCommand:
  278.    }
  279.  
  280. executive(s)
  281. unsigned char  *s;
  282. {
  283.    struct   FileLock *fl;
  284.    unsigned char     *pc;
  285.  
  286.    /*
  287.     * get the first token off of the command line into work.
  288.     */
  289.    pc = work;
  290.    while ((*pc = *s) != ' ' && *pc != '\0') {
  291.       pc++;
  292.       s++;
  293.       }
  294.    *pc = '\0';
  295.    strcpy(work2, work);       /* save first token in work2 */
  296.  
  297.    /*
  298.     * check for MyCLI batch file invocation.
  299.     */
  300.    strcat(work, ".bat");
  301.    fl = Lock(work, ACCESS_READ);
  302.    if (fl != 0) {             /* MyCLI batch file exists */
  303.       UnLock(fl);             /* free the lock obtained */
  304.       batchfile(work);        /* execute the batch file */
  305.       goto execfini;          /* done our work */
  306.       }
  307.    /*
  308.     * skip forward to 1st argument.  This is what is passed as arguments
  309.     * to the executed cli batch file or amigados program to be invoked.
  310.     */
  311.    s = stpblk(s);
  312.    /*
  313.     * .cli files are batch files to be run by the
  314.     * standard cli, using the execute command.
  315.     */
  316.    strcpy(work, work2);       /* preserve the first token again */
  317.    strcat(work2, ".cli");
  318.    fl = Lock(work2, ACCESS_READ);
  319.    if (fl == 0)               /* cli batch file doesn't exist */
  320.       strcpy(work2, work);    /* restore first token */
  321.    UnLock(fl);                /* free the lock obtained */
  322.    if (*s != '\0') {          /* parameters are to be passed */
  323.       strcat(work2, " ");     /* add a space */
  324.       strcat(work2, s);       /* and the parameters */
  325.       }
  326.    if (!Execute(work2, 0, mycli_outfp))
  327.       doserr();
  328. execfini:
  329.    }
  330.  
  331. doserr() {
  332.    sprintf(buf, "%d", IoErr());
  333.    whatis(buf);
  334.    }
  335.  
  336. capture(s)
  337. unsigned char  *s;
  338. {
  339.    if (!modem_online) {
  340.       sprintf(work, "%c[36mCapture Fehler: nicht online%c[0m\n", 0x1b, 0x1b);
  341.       WriteWork();
  342.       }
  343.    else if (capturing_file) {
  344.       Close(capture_fp);
  345.       sprintf(work, "%c[36mCapture fertig%c[0m\n", 0x1b, 0x1b);
  346.       WriteWork();
  347.       capturing_file = 0;
  348.       }
  349.    else {
  350.       capture_fp = Open(s, MODE_NEWFILE);
  351.       if (capture_fp == 0)
  352.          doserr();
  353.       else {
  354.          capturing_file = !0;
  355.          sprintf(work,
  356.                  "%c[36mCapturing File - capture nochmal um zu beenden%c[0m\n",
  357.                  0x1b, 0x1b);
  358.        WriteWork();
  359.          }
  360.       }
  361.    }
  362.  
  363. cd(s)
  364. unsigned char  *s;
  365. {
  366.    int   i;
  367.  
  368.    strcpy(temp, current_directory);
  369.    if (*s == '\0') {
  370.       sprintf(work, "%-30s\n", current_directory);
  371.       WriteWork();
  372.       }
  373.    else {
  374.       if (*s == '/') {
  375.          s++;
  376.          for (i=strlen(current_directory);
  377.               current_directory[i] != '/' && current_directory[i] != ':';
  378.               i--);
  379.          current_directory[i+1] = '\0';
  380.          strcat(current_directory, s);
  381.          }
  382.       else if (stpchr(s, ':') == 0) {
  383.          if (current_directory[strlen(current_directory)-1] != ':')
  384.             strcat(current_directory, "/");
  385.          strcat(current_directory, s);
  386.          }
  387.       else
  388.          strcpy(current_directory, s);
  389.       worklock = Lock(current_directory, ACCESS_READ);
  390.       if (worklock == 0) {
  391.          doserr();
  392.          strcpy(current_directory, temp);
  393.          }
  394.       else if (Examine(worklock, &fib)) {
  395.          if (fib.fib_DirEntryType > 0) {
  396.             worklock = CurrentDir(worklock);
  397.             if (worklock != 0)
  398.                UnLock(worklock);
  399.             }
  400.          else {
  401.             sprintf(work, "%c[36mCD Fehler: keine Directory (%d) %c[0m\n",
  402.                     0x1b, fib.fib_DirEntryType, 0x1b);
  403.             WriteWork();
  404.             strcpy(current_directory, temp);
  405.             }
  406.          }
  407.       else
  408.          doserr();
  409.       }
  410.    }
  411.  
  412. copy(s)
  413. unsigned char  *s;
  414. {
  415.    unsigned    char  *pc;
  416.    struct      FileHandle  *copyin;
  417.    struct      FileHandle  *copyout;
  418.    int         iosize;
  419.    int         actual;
  420.    unsigned    char        *copybuf;
  421.  
  422.    if (strncmp(s, "from", 4) == 0)
  423.       s = stpblk(&s[4]);
  424.    for (pc = s; !isspace(*pc); pc++);
  425.    *pc++ = '\0';
  426.    pc = stpblk(pc);
  427.    if (strncmp(pc, "to", 2) == 0)
  428.       pc = stpblk(&pc[2]);
  429.  
  430. /*  printf("kopiere von %s zu %s\n", s, pc);  */
  431.    /*
  432.     * check from filename for console.
  433.     */
  434.    if (strncmp(s, "con:", 4) == '*')
  435.       copyin = mycli_infp;
  436.    else
  437.       copyin = Open(s, MODE_OLDFILE);
  438.    if (copyin == 0)
  439.       doserr();
  440.    /*
  441.     * second parameter
  442.     */
  443.    else {
  444.       /*
  445.        * console device?
  446.        */
  447.       if (strncmp(pc, "con:", 4) == 0)
  448.          copyout = mycli_outfp;
  449.       /*
  450.        * no second parameter?
  451.        */
  452.       else if (*pc == '\0') {
  453.          /*
  454.           * separate filename from path specification/filename
  455.           * or device:path/filename or simple filename
  456.           * in from field.
  457.           */
  458.          pc = &s[strlen(s)-1];   /* end of string */
  459.          while (pc != s && *pc != ':' && *pc != '/')
  460.             pc--;
  461.          /*
  462.           * build an appropriate file specification for output
  463.           * file.
  464.           */
  465.          strcpy(work, current_directory);
  466.          /*
  467.           * from device:filespec?
  468.           */
  469.          if (*pc == ':') {
  470.             pc++;
  471.             strcat(work, pc);
  472.             }
  473.          else {
  474.             strcat(work, "/");
  475.             /*
  476.              * don't want //
  477.              */
  478.             if (*pc == '/')
  479.                pc++;
  480.             strcat(work, pc);
  481.             }
  482. /*  printf("Openning %s for output\n", work);  */
  483.          copyout = Open(work, MODE_NEWFILE);
  484.          }
  485.       else {
  486. /*  printf("Openning %s for output\n", pc);  */
  487.         copyout = Open(pc, MODE_NEWFILE);
  488.          }
  489.       if (copyout == 0) {
  490.          doserr();
  491.          Close(copyin);
  492.          }
  493.       else {
  494.          /*
  495.           * here is how to determine the length of a
  496.           * file.  This is the most desirable Amount
  497.           * to read from the from file, because it
  498.           * requires one head seek, and allows the
  499.           * entire track buffer to be used for the
  500.           * read.
  501.           */
  502.          iosize = Seek(copyin, 0, OFFSET_END);
  503.          iosize = Seek(copyin, 0, OFFSET_BEGINING);
  504.  
  505.          /*
  506.           * maybe there isn't enough memory to hold
  507.           * the entire from file.  the following
  508.           * algorithm determines whether 1/2 the
  509.           * file file, 1/4, 1/8, etc., will fit
  510.           * in memory at a time.  if 512 bytes can't
  511.           * be allocated, then there is not enough
  512.           * memory to do the copy at all.
  513.           */
  514.          do {
  515.             copybuf = AllocMem(iosize, MEMF_PUBLIC|MEMF_CLEAR);
  516.             if (copybuf == 0)
  517.                iosize = iosize/2;
  518.             }
  519.          while (copybuf == 0 & iosize > 512);
  520.          if (copybuf == 0) {
  521.             sprintf(work,
  522.                     "%c[36mCopy Fehler: nicht genug Speicher%c[0m\n",
  523.                     0x1b, 0x1b);
  524.             WriteWork();
  525.             }
  526.          else
  527.             do {
  528.                actual = Read(copyin, copybuf, iosize);
  529.                if (Write(copyout, copybuf, actual) != actual) {
  530.                   doserr();
  531.                   break;
  532.                   }
  533.                }
  534.             while (actual == iosize);
  535.          if (copyin != mycli_infp)
  536.             Close(copyin);
  537.          if (copyout != mycli_outfp)
  538.             Close(copyout);
  539.          FreeMem(copybuf, iosize);
  540.          }
  541.       }
  542.    }
  543.  
  544. date(s)
  545. unsigned char  *s;
  546. {
  547.    struct   DateStamp   dss;
  548.  
  549.    DateStamp(&dss);
  550.    dates(work, &dss);
  551.    strcat(work, "\n");
  552.    WriteWork();
  553.    }
  554.  
  555. define_function_key(s)
  556. unsigned char  *s;
  557. {
  558.    int   i;
  559.  
  560.    if (s[0] == '\0')
  561.       for (i=0; i<20; i++) {
  562.          if (function_key_definitions[i]) {
  563.             sprintf(work, "F%-2d = %s\n", i+1, function_key_definitions[i]);
  564.             WriteWork();
  565.             }
  566.          }
  567.    else if (s[0] == 'f' || s[0] == 'F') {
  568.       s++;
  569.       i = atoi(s);
  570.       if (i < 1 || i > 20) {
  571.          sprintf(work, "%c[36munzulässige Funktionstaste%c[0m\n", 0x1b, 0x1b);
  572.          WriteWork();
  573.          }
  574.       else {
  575.          i--;
  576.          if (function_key_definitions[i])
  577.             FreeMem(function_key_definitions[i], strlen(function_key_definitions[i])+1);
  578.          while (isdigit(*s))
  579.             s++;
  580.          s = stpblk(s);
  581.          if (*s != '\0') {
  582.             function_key_definitions[i] = AllocMem(strlen(s)+1, MEMF_PUBLIC|MEMF_CLEAR);
  583.             if (function_key_definitions[i] == 0) {
  584.                sprintf(work, "%c[36mDefine Fehler: nicht genug Speicher%c[0m\n",
  585.                         0x1b, 0x1b);
  586.                WriteWork();
  587.                }
  588.             else
  589.                strcpy(function_key_definitions[i], s);
  590.             }
  591.          }
  592.       }
  593.    else {
  594.       sprintf(work,
  595.               "%c[36mDefine Fehler: Falsche Definition%c[0m\n",
  596.               0x1b, 0x1b);
  597.       WriteWork();
  598.       }
  599.    }
  600.  
  601. delete(s)
  602. unsigned char  *s;
  603. {
  604.    if (!DeleteFile(s))
  605.       doserr();
  606.    }
  607.  
  608. dir(s)
  609. unsigned char  *s;
  610. {
  611.    int   filecount, bytecount, blockcount, dircount;
  612.  
  613.    filecount = bytecount = blockcount = dircount = 0;
  614.  
  615.    if (*s == '\0')
  616.       strcpy(work, current_directory);
  617.    else
  618.       strcpy(work, s);
  619.    worklock = Lock(work, ACCESS_READ);
  620.    if (worklock == 0)
  621.       doserr();
  622.    else {
  623.       if (!Examine(worklock, &fib))
  624.          doserr();
  625.       else {
  626.          sprintf(buf, "\nDirectory von %s\n", work);
  627.          Write(mycli_outfp, buf, strlen(buf));
  628.          if (!Info(worklock, &disk_info))
  629.             doserr();
  630.          else {
  631.             sprintf(work,
  632. "%c[7mEinheit: %2d Fehler: %3d  Blockgröße: %3d Blöcke: %4d  Blöcke voll: %4d  %c[0m\n",
  633.                0x1b,
  634.                disk_info.id_UnitNumber,
  635.                disk_info.id_NumSoftErrors,
  636.                disk_info.id_BytesPerBlock,
  637.                disk_info.id_NumBlocks,
  638.                disk_info.id_NumBlocksUsed,
  639.                0x1b);
  640.             WriteWork();
  641.             }
  642.          sprintf(work,
  643.           "%c[7m%-30sSchutz   Größe  Blöcke Kommentare           %c[0m\n",
  644.           0x1b, "FileName", 0x1b);
  645.          WriteWork();
  646.          if (fib.fib_DirEntryType < 0) {
  647.             showfib();
  648.             if (fib.fib_DirEntryType > 0)
  649.                dircount++;
  650.             else
  651.                filecount++;
  652.             bytecount += fib.fib_Size;
  653.             blockcount += fib.fib_NumBlocks;
  654.             }
  655.          else
  656.             while(ExNext(worklock, &fib)) {
  657.                showfib();
  658.                if (fib.fib_DirEntryType > 0)
  659.                   dircount++;
  660.                else
  661.                   filecount++;
  662.                bytecount += fib.fib_Size;
  663.                blockcount += fib.fib_NumBlocks;
  664.                if (!pause())
  665.                   break;
  666.                }
  667.          sprintf(work, "%c[7m%3d Unterdirectories %3d Files %7dBytes %6d Blocks %7dBytes Frei%c[0m\n",
  668.             0x1b,
  669.             dircount, filecount, bytecount, blockcount,
  670.             (disk_info.id_NumBlocks - disk_info.id_NumBlocksUsed) *
  671.                                              disk_info.id_BytesPerBlock,
  672.             0x1b);
  673.          WriteWork();
  674.          UnLock(worklock);
  675.          }
  676.       }
  677.    }
  678.  
  679. showfib() {
  680.    sprintf(work, "%-30s ", fib.fib_FileName);
  681.    WriteWork();
  682.    if (fib.fib_DirEntryType > 0) {
  683.       sprintf(work, "Unterdirectory       ");
  684.       WriteWork();
  685.       }
  686.    else {
  687.       sprintf(work, "%c%c%c%c %6d %6d ",
  688.             (fib.fib_Protection&FIBF_READ) ? ' ' : 'R',
  689.             (fib.fib_Protection&FIBF_WRITE) ? ' ' : 'W',
  690.             (fib.fib_Protection&FIBF_EXECUTE) ? ' ' : 'E',
  691.             (fib.fib_Protection&FIBF_DELETE) ? ' ' : 'D',
  692.             fib.fib_Size,
  693.             fib.fib_NumBlocks);
  694.       WriteWork();
  695.       }
  696.    sprintf(work, "%s\n", fib.fib_Comment);
  697.    WriteWork();
  698.    }
  699.  
  700. endcli(s)
  701. unsigned char  *s;
  702. {
  703.    if (modem_online) {
  704.       sprintf(work, "%c[36mTerminal Mode Fehler: Modem noch online%c[0m\n",
  705.               0x1b, 0x1b);
  706.       WriteWork();
  707.       }
  708.    else {
  709.       Close(mycli_outfp);
  710.       exit(0);
  711.       }
  712.    }
  713.  
  714. help(s)
  715. unsigned char  *s;
  716. {
  717.    int   i;
  718.  
  719.    sprintf(work,
  720.                  "%c[7m          MeinCli Hilfstext          %c[0m\n", 0x1b, 0x1b);
  721.    WriteWork();
  722.    for (i=0; help_messages[i]; i++) {
  723.       sprintf(work, "%s\n", help_messages[i]);
  724.       WriteWork();
  725.       if (!pause())
  726.          break;
  727.       }
  728.    sprintf(work, "%c[7m        Ende der Hilfstexte          %c[0m\n", 0x1b, 0x1b);
  729.    WriteWork();
  730.    }
  731.  
  732. md(s)
  733. unsigned char  *s;
  734. {
  735.    worklock = CreateDir(s);
  736.    if (worklock == 0)
  737.       doserr();
  738.    else
  739.       UnLock(worklock);
  740.    }
  741.  
  742. newcli(s)
  743. unsigned char  *s;
  744. {
  745.    sprintf(work, "run meincli %d", mycli_id+1);
  746.    if (!Execute(work, 0, mycli_outfp))
  747.       doserr();
  748.    }
  749.  
  750. offline(s)
  751. unsigned char  *s;
  752. {
  753.    modem_online = 0;
  754.    }
  755.  
  756. rename(s)
  757. unsigned char  *s;
  758. {
  759.    unsigned char  *pc;
  760.  
  761.    for (pc = s; !isspace(*pc); pc++);
  762.    *pc++ = '\0';
  763.    pc = stpblk(pc);
  764.    if (strncmp(pc, "to", 2) == 0)
  765.       pc = stpblk(&pc[2]);
  766.    if (!Rename(s, pc))
  767.       doserr();
  768.    }
  769.  
  770. setcomment(s)
  771. unsigned char  *s;
  772. {
  773.    unsigned char  *pc;
  774.  
  775.    for (pc = s; *pc != ' ' && *pc != '\t' && *pc != '\0'; pc++);
  776.    *pc++ = '\0';
  777.    pc = stpblk(pc);
  778.    if (!SetComment(s, pc))
  779.       doserr();
  780.    }
  781.  
  782. setprompt(s)
  783. unsigned char  *s;
  784. {
  785.    if (prompt_string != 0)
  786.       FreeMem(prompt_string, strlen(prompt_string)+1);
  787.    prompt_string = AllocMem(strlen(s)+1, MEMF_PUBLIC|MEMF_CLEAR);
  788.    if (prompt_string == 0) {
  789.       sprintf(work, "AllocMem abgebrochen\n");
  790.       WriteWork();
  791.       prompt_string = 0;
  792.       }
  793.    strcpy(prompt_string, s);
  794.    }
  795.  
  796. showprompt() {
  797.    unsigned char     *pc;
  798.    struct   DateStamp   dss;
  799.  
  800.    if (prompt_string == 0) {
  801.       sprintf(work, "MeinCli rev. 1.00\n");
  802.       WriteWork();
  803.       }
  804.    else {
  805.       pc = prompt_string;
  806.       while (1) {
  807.          switch(*pc) {
  808.             case '\0':
  809.                break;
  810.             case '$':
  811.                pc++;
  812.                switch(*pc) {
  813.                   case '\0':
  814.                      continue;
  815.                   case 'd':
  816.                   case 'D':
  817.                      DateStamp(&dss);
  818.                      dates(work, &dss);
  819.                      WriteWork();
  820.                      break;
  821.                   case 't':
  822.                   case 'T':
  823.                      DateStamp(&dss);
  824.                      times(work, &dss);
  825.                      WriteWork();
  826.                      break;
  827.                   case 'v':
  828.                   case 'V':
  829.                      sprintf(work, "MeinCli rev. 1.00");
  830.                      WriteWork();
  831.                      break;
  832.                   case 'p':
  833.                   case 'P':
  834.                      sprintf(work, "%s", current_directory);
  835.                      WriteWork();
  836.                      break;
  837.                   case 'r':         /* reverse video */
  838.                   case 'R':
  839.                      sprintf(work, "%c[7m", 0x1b);
  840.                      WriteWork();
  841.                      break;
  842.                   case 'n':         /* normal video */
  843.                   case 'N':
  844.                      sprintf(work, "%c[0m", 0x1b);
  845.                      WriteWork();
  846.                      break;
  847.                   case '_':
  848.                      strcpy(work, "\n");
  849.                      WriteWork();
  850.                      break;
  851.                   }
  852.                pc++;
  853.                continue;
  854.             default:
  855.                sprintf(work, "%c", *pc++);
  856.                WriteWork();
  857.                continue;
  858.             }
  859.          break;
  860.          }
  861.       }
  862.    }
  863.  
  864. TerminalMode(s)
  865. unsigned char  *s;
  866. {
  867.    modem_online = !0;      /* signal that modem is live !!! */
  868.    if (initialize()) {     /* set baud rate, etc. */
  869.       Write(mycli_outfp, WelcomeMessage, strlen(WelcomeMessage));
  870.       while (modem_online) {
  871.          bdoneflag = 0;    /* terminal mode on flag */
  872.          Write(mycli_outfp, OnlineMessage, strlen(OnlineMessage));
  873.          while (!bdoneflag) {
  874.             check_keyboard();
  875.             check_modem();
  876.             }
  877.          Write(mycli_outfp, OfflineMessage, strlen(OfflineMessage));
  878.          showprompt();
  879.          getcommand(buf);
  880.          CommandInterpreter(buf);
  881.          }
  882.       cleanup();
  883.       }
  884.    modem_online = 0;
  885.    }
  886.  
  887. time(s)
  888. unsigned char  *s;
  889. {
  890.    struct   DateStamp   dss;
  891.  
  892.    DateStamp(&dss);
  893.    times(work, &dss);
  894.    strcat(work, "\n");
  895.    WriteWork();
  896.    }
  897.  
  898. type(s)
  899. unsigned char  *s;
  900. {
  901.    int   len, len2;
  902.    unsigned char c;
  903.  
  904.    workfp = Open(s, MODE_OLDFILE);
  905.    if (workfp == 0)
  906.       doserr();
  907.    else {
  908.       do {
  909.          len = Read(workfp, buf, 512);
  910.          for (len2 = 0; len2 < len; len2++) {
  911.             Write(mycli_outfp, &buf[len2], 1);
  912.             if (modem_online) {
  913.                rs_out[0] = buf[len2];
  914.                DoIO(ModemWriteRequest);
  915.                if (!TermEcho) {        /* characters will be echoed back */
  916.                   WaitIO(ModemReadRequest); /* get the echoed character */
  917.                   c = rs_in[0];
  918.                   BeginIO(ModemReadRequest);
  919.                   }
  920.                }
  921.             if (!pause()) {
  922.                len = 0;
  923.                break;
  924.                }
  925.             }
  926.          }
  927.          while (len == 512);
  928.       sprintf(work, "\n%c[36m*** Ende des Files%c[0m\n", 0x1b, 0x1b);
  929.       WriteWork();
  930.       Close(workfp);
  931.       }
  932.    }
  933.  
  934. whatis(s)
  935. unsigned char  *s;
  936. {
  937.    int   errorcode;
  938.    int   i;
  939.  
  940.    if (*s < '0' || *s > '9') {
  941.       sprintf(work, "Entkräfteter Errorcode spezifiziert\n");
  942.       WriteWork();
  943.       }
  944.    else {
  945.       errorcode = atoi(s);
  946.       if (errorcode) {
  947.          for (i=0; errorcodes[i].code; i++)
  948.             if (errorcodes[i].code == errorcode)
  949.                break;
  950.          if (errorcodes[i].code == errorcode)
  951.             strcpy(work, errorcodes[i].message);
  952.          else
  953.             strcpy(work, "undocumented AmigaDos error code");
  954.          sprintf(buf, "%c[36mAmigaDos Error %d: %s%c[0m\n", 0x1b, errorcode,
  955.                  work, 0x1b);
  956.          Write(mycli_outfp, buf, strlen(buf));
  957.          }
  958.       }
  959.    }
  960.  
  961. /*
  962.  * get the date and make it into a printable string
  963.  */
  964. unsigned char  *months[12] = {
  965.    "Januar", "Febuar", "März", "April", "Mai", "Juni",
  966.    "Juli", "August", "September", "Oktober", "November", "Dezember"
  967.    };
  968.  
  969. UBYTE dayspermonth1[12] = {   /* leap years */
  970.    31, 29, 31, 30, 31, 30,
  971.    31, 31, 30, 31, 30, 31
  972.    };
  973.  
  974. UBYTE dayspermonth2[12] = {   /* non leap years */
  975.    31, 28, 31, 30, 31, 30,
  976.    31, 31, 30, 31, 30, 31
  977.    };
  978.  
  979. dates(s, dss)
  980. unsigned char  *s;
  981. struct DateStamp *dss;
  982. {
  983.    int   year;
  984.    int   month;
  985.    int   day;
  986.  
  987.    year = 1978;
  988.    day = dss->ds_Days;
  989.    while (day >= 366) {
  990.       if ( (year-1976) % 4 == 0) {
  991.          day -= 366;
  992.          year++;
  993.          }
  994.       else if ( (year-1976) % 4 != 0 && day >= 365) {
  995.          day -= 365;
  996.          year++;
  997.          }
  998.       }
  999.    if ( (year-1976) % 4 == 0) {
  1000.       day = day % 366;
  1001.       for (month = 0; day > dayspermonth1[month]; month++)
  1002.          day -= dayspermonth1[month];
  1003.       }
  1004.    else {
  1005.       day = day % 365;
  1006.       for (month = 0; day > dayspermonth2[month]; month++)
  1007.          day -= dayspermonth2[month];
  1008.       }
  1009.    sprintf(s, "%s %d, %d", months[month], day+1, year);
  1010.    }
  1011.  
  1012. times(s, dss)
  1013. unsigned char  *s;
  1014. struct DateStamp *dss;
  1015. {
  1016.    int   hours, minutes, seconds;
  1017.  
  1018.    seconds = dss->ds_Tick / 50;
  1019.    seconds %= 60;
  1020.    minutes = dss->ds_Minute;
  1021.    hours = minutes / 60;
  1022.    minutes %= 60;
  1023.    if (hours == 0)
  1024.       hours = 24;
  1025.    sprintf(s, "%d:%02d:%02d.%d ", (hours>12)?hours-12:hours, minutes,
  1026.            seconds, (dss->ds_Tick % 50)*2);
  1027.    if (hours < 12)
  1028.       strcat(s, "am Morgen");
  1029.    else if (hours == 12)
  1030.       strcat(s, "am Mittag");
  1031.    else if (hours < 19)
  1032.       strcat(s, "am Nachmittag");
  1033.    else if (hours < 21)
  1034.       strcat(s, "am Abend");
  1035.    else if (hours == 24)
  1036.       strcat(s, "Nachts");
  1037.    else
  1038.       strcat(s, "Zeit zum schlafen");
  1039.    }
  1040.  
  1041. unsigned char  scr_csts() {
  1042.    unsigned char inbuf[2];
  1043.  
  1044.    if (WaitForChar(mycli_infp, 1) == 0)
  1045.       return 0;
  1046.    Read(mycli_infp, &inbuf[0], 1);
  1047.    return inbuf[0];
  1048.    }
  1049.  
  1050. pause() {
  1051.    unsigned char inbuf[2];
  1052.  
  1053.    switch(scr_csts()) {
  1054.       case ' ':
  1055.          while ((inbuf[0] = scr_csts()) != ' ')
  1056.             if (inbuf[0] == 0x1b) {
  1057.                return 0;
  1058.                }
  1059.          return !0;
  1060.       case 0x1b:
  1061.          return 0;
  1062.       default:
  1063.          return !0;
  1064.       }
  1065.    }
  1066.  
  1067. getcommand(s)
  1068. unsigned char  *s;
  1069. {
  1070.    unsigned char  c;
  1071.    unsigned col;
  1072.  
  1073.    col = 0;
  1074.    while (1) {
  1075.       Read(mycli_infp, &c, 1);
  1076.       switch(c) {
  1077.          case 8:
  1078.             if (col) {
  1079.                c = 8;
  1080.                Write(mycli_outfp, &c, 1);
  1081.                c = ' ';
  1082.                Write(mycli_outfp, &c, 1);
  1083.                c = 8;
  1084.                Write(mycli_outfp, &c, 1);
  1085.                col--;
  1086.                }
  1087.             continue;
  1088.          case 10:
  1089.          case 13:
  1090.             sprintf(work, "\n");
  1091.             WriteWork();
  1092.             s[col++] = '\0';
  1093.             break;
  1094.          case 0x1b:
  1095.          case 24:
  1096.             while (col) {
  1097.                c = 8;
  1098.                Write(mycli_outfp, &c, 1);
  1099.                c = ' ';
  1100.                Write(mycli_outfp, &c, 1);
  1101.                c = 8;
  1102.                Write(mycli_outfp, &c, 1);
  1103.                col--;
  1104.                }
  1105.             continue;
  1106.          case 0x9b:
  1107.             if (process_event(&s[col])) {
  1108.                strcat(s, "\n");
  1109.                Write(mycli_outfp, &s[col], strlen(&s[col]));
  1110.                break;
  1111.                }
  1112.             continue;
  1113.          default:
  1114.             s[col++] = c;
  1115.             Write(mycli_outfp, &c, 1);
  1116.             continue;
  1117.          }
  1118.       break;
  1119.       }
  1120.    }
  1121.  
  1122. /*
  1123.  * this function converts an incoming ANSI escape sequence
  1124.  * and processes it.  A buffer is passed where any function
  1125.  * key expansion is to take place. If the buffer is modified
  1126.  * for any reason, this function returns true.
  1127.  */
  1128. process_event(cmd_line)
  1129. unsigned char  *cmd_line;
  1130. {
  1131.    int   i;
  1132.    unsigned char  c;
  1133.    char  event_buffer[32];
  1134.  
  1135.    i = 0;
  1136.    while (1) {
  1137.       Read(mycli_infp, &c, 1);
  1138.       event_buffer[i] = c;
  1139.       if (c == '~' || c == '|')
  1140.          break;
  1141.       i++;
  1142.       }
  1143.    event_buffer[i+1] = '\0';
  1144.    if (event_buffer[i] == '~') {
  1145.       if (event_buffer[0] == '?') {
  1146.          strcpy(cmd_line, "help");
  1147.          return !0;
  1148.          }
  1149.       else if (isdigit(event_buffer[0])) {
  1150.          if (function_key(atoi(event_buffer), cmd_line))
  1151.             return !0;
  1152.          }
  1153.       }
  1154.    return 0;
  1155.    }
  1156.  
  1157. /*
  1158.  * if a definition for the function key fkey exists (0-19), then
  1159.  * the translation for the function key is copied to the string
  1160.  * s, and this function returns !0.  Otherwise, now translation
  1161.  * exists, and this function returns 0.
  1162.  */
  1163. function_key(fkey, s)
  1164. int   fkey;
  1165. unsigned char  *s;
  1166. {
  1167.    int   i;
  1168.  
  1169.    if (function_key_definitions[fkey] != 0) {
  1170.       for (i=0; function_key_definitions[fkey][i] != '\0'; i++)
  1171.          s[i] = function_key_definitions[fkey][i];
  1172.       s[i] = '\0';
  1173.       return !0;
  1174.       }
  1175.    return 0;
  1176.    }
  1177.  
  1178. initialize() {
  1179.    ModemReadRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemReadRequest),
  1180.                       MEMF_PUBLIC | MEMF_CLEAR);
  1181.    ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  1182.    ModemReadRequest->IOSer.io_Message.mn_ReplyPort =
  1183.                                             CreatePort("Read_RS",0);
  1184.    if (OpenDevice(SERIALNAME, NULL, ModemReadRequest, NULL)) {
  1185.       sprintf(work, "%c[36mCan't open serial read device%c[0m\n",
  1186.               0x1b, 0x1b);
  1187.       WriteWork();
  1188.       DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
  1189.       FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
  1190.       return 0;
  1191.       }
  1192.    ModemReadRequest->IOSer.io_Command = CMD_READ;
  1193.    ModemReadRequest->IOSer.io_Length = 1;
  1194.    ModemReadRequest->IOSer.io_Data = (APTR) &rs_in[0];
  1195.  
  1196.    ModemWriteRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemWriteRequest),
  1197.                       MEMF_PUBLIC | MEMF_CLEAR);
  1198.    ModemWriteRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  1199.    ModemWriteRequest->IOSer.io_Message.mn_ReplyPort =
  1200.                                                   CreatePort("Write_RS",0);
  1201.    if (OpenDevice(SERIALNAME, NULL, ModemWriteRequest, NULL)) {
  1202.       sprintf(work, "%c[36mCan't open serial write device%c[0m\n",
  1203.               0x1b, 0x1b);
  1204.       WriteWork();
  1205.       DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
  1206.       FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
  1207.       DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
  1208.       FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
  1209.       return 0;
  1210.       }
  1211.    ModemWriteRequest->IOSer.io_Command = CMD_WRITE;
  1212.    ModemWriteRequest->IOSer.io_Length = 1;
  1213.    ModemWriteRequest->IOSer.io_Data = (APTR) &rs_out[0];
  1214.  
  1215.    ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  1216.    ModemReadRequest->io_Baud = 1200;
  1217.    ModemReadRequest->io_ReadLen = 8;
  1218.    ModemReadRequest->io_WriteLen = 8;
  1219.    ModemReadRequest->io_CtlChar = 1L;
  1220.    ModemReadRequest->IOSer.io_Command = SDCMD_SETPARAMS;
  1221.    DoIO(ModemReadRequest);
  1222.    ModemReadRequest->IOSer.io_Command = CMD_READ;
  1223.    BeginIO(ModemReadRequest);
  1224.    return !0;
  1225.    }
  1226.  
  1227. cleanup() {
  1228.    CloseDevice(ModemReadRequest);
  1229.    DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
  1230.    FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
  1231.  
  1232.    CloseDevice(ModemWriteRequest);
  1233.    DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
  1234.    FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
  1235.  
  1236.    Write(mycli_outfp, GoodbyeMessage, strlen(GoodbyeMessage));
  1237.    }
  1238.  
  1239. check_keyboard() {
  1240.    unsigned char  *pc;
  1241.  
  1242.    if (WaitForChar(mycli_infp, 1)) {
  1243.       Read(mycli_infp, &rs_out[0], 1);
  1244.       switch ((unsigned char)rs_out[0]) {
  1245.          case 0x03:                          /* escape to command mode */
  1246.             bdoneflag = !0;
  1247.             break;
  1248.          case 0x9b:                          /* ANSI keyboard stuff */
  1249.             if (process_event(&buf[0])) {    /* send the translation */
  1250.                pc = &buf[0];
  1251.                while (*pc != '\0') {
  1252.                   rs_out[0] = *pc++;
  1253.                   if (TermEcho)
  1254.                      Write(mycli_outfp, &rs_out[0], 1);
  1255.                   DoIO(ModemWriteRequest);
  1256.                   check_modem();
  1257.                   }
  1258.                rs_out[0] = '\n';
  1259.                if (TermEcho)
  1260.                   Write(mycli_outfp, &rs_out[0], 1);
  1261.                DoIO(ModemWriteRequest);
  1262.                rs_out[0] = '\r';
  1263.                DoIO(ModemWriteRequest);
  1264.                }
  1265.             break;
  1266.          case 0x05:                    /* toggle keystroke echo */
  1267.             TermEcho = !TermEcho;
  1268.             sprintf(work, "%c[36mEcho %s%c[0m\n", 0x1b, TermEcho?"ON":"OFF",
  1269.                       0x1b);
  1270.             WriteWork();
  1271.             break;
  1272.          default:
  1273.             if (TermEcho)
  1274.                Write(mycli_outfp, &rs_out[0], 1);
  1275.             DoIO(ModemWriteRequest);
  1276.          }
  1277.       }
  1278.    }
  1279.  
  1280. /*
  1281.  * Check to see of the Read Request IO has completed from the modem.
  1282.  */
  1283. check_modem() {
  1284.    if (CheckIO(ModemReadRequest)) {
  1285.       WaitIO(ModemReadRequest);
  1286.       rs_in[0] &= 0x7f;
  1287.       Write(mycli_outfp, &rs_in[0], 1);
  1288.       if (capturing_file)
  1289.          Write(capture_fp, &rs_in[0], 1);
  1290.       BeginIO(ModemReadRequest);
  1291.       }
  1292.    }
  1293.